import { z } from "zod"; import { validate } from "#server/utils/validation"; import { updateArticle, getArticleById, ArticleStatuses } from "../../service/article"; import { requireUser, delCache } from "#server/utils/context"; const updateSchema = z.object({ title: z.string().min(1, "标题不能为空").max(255, "标题不能超过 255 字").optional(), content: z.string().min(1, "内容不能为空").optional(), summary: z.string().max(500, "摘要不能超过 500 字").nullable().optional(), cover: z.string().max(500).nullable().optional(), status: z.enum(ArticleStatuses).optional(), cardIds: z .array( z.object({ cardId: z.number().int().positive("无效的卡片 ID"), sortOrder: z.number().int().optional(), }), ) .nullable() .optional(), }); export default defineWrappedResponseHandler(async (event) => { await requireUser(event); const idParam = getRouterParam(event, "id"); if (!idParam) return R.throwError(400, "缺少文章 ID", null); const id = parseInt(idParam); if (isNaN(id)) return R.throwError(400, "文章 ID 格式不正确", null); const existing = await getArticleById(id); if (!existing) return R.throwError(404, "文章不存在", null); const body = await readBody(event); const data = validate(updateSchema, body); const updated = await updateArticle(id, data); if (!updated) return R.throwError(500, "更新失败", null); // Clear card caches for both old and new card associations const oldCardIds = new Set(existing.cards.map((c) => c.id)); const newCardIds = new Set(updated.cards.map((c) => c.id)); const affectedCardIds = new Set([...oldCardIds, ...newCardIds]); if (affectedCardIds.size > 0) { await Promise.all([...affectedCardIds].map((cid) => delCache(`card:${cid}`))); } return R.success(updated); });